#include "dl_definitions.h"

#define inc_link_data(x) (a_inc_link_data[x-1])

static INC_LINK_DATA*	a_inc_link_data;	//array of data for each outgoing link; size is c_out_links

void draw_frame(CnetEvent ev, CnetTimerID timer, CnetData data)
{
    CnetDrawFrame *df  = (CnetDrawFrame *)data;
    FRAME         *f   = (FRAME *)df->frame;

	df->nfields    = 1;
	df->colours[0] = (f->last_segment > 99) ? "red" : "purple";
	df->pixels[0]  = 10;
	sprintf(df->text, "seq=%d", f->last_segment);
	
}
//reads a message from physical layer and passes it (currently) to app layer and invokes ACK handling
static void DL_receive_frame (CnetEvent ev, CnetTimerID timer, CnetData data) {
	
	/*
	 * creating a frame
	 */
    FRAME        f;
    size_t       len;
    int          link;
    len         = sizeof(FRAME);

    CHECK(CNET_read_physical(&link, (char *)&f, &len));			//obtaining a frame from the physical layer
	
	//first frame of a packet
	if (inc_link_data(link).c_curr_part == 0) {
		inc_link_data(link).seq = f.last_segment;
	} else {
		if (f.last_segment != inc_link_data(link).seq && 
			(f.last_segment - 100) != inc_link_data(link).seq) {//seems that we've lost the last frame
			
			inc_link_data(link).c_curr_part = 0;					//resetting vars for next packet
			inc_link_data(link).infolen = 0;
			inc_link_data(link).seq = f.last_segment;
		}
		
	}
	
	
	/*
	 * computation: ptr to packet destination + offset
	 * offset = number of processed chunks times their size (based on mtu only)
	 */
	size_t offset = inc_link_data(link).c_curr_part * inc_link_data(link).s_max_chunk;
	size_t frameinfo_len = len - FRAME_HEADER_SIZE;
	if (offset + (frameinfo_len) > sizeof(INFO)){
			inc_link_data(link).c_curr_part = 0;					//resetting vars for next packet
			inc_link_data(link).infolen = 0;
			return;
	}

	char* ptr_chunk = (char*) &inc_link_data(link).curr_info + offset;
//	fprintf(stderr, "%s DL_receive_frame(): ptr_chunk=0x%x, &f.info=0x%x, frameinfo_len=%u, offset=%u\n", nodeinfo.nodename, (uint32_t)ptr_chunk, (uint32_t)&(f.info), frameinfo_len, offset);
	memcpy(ptr_chunk, &(f.info), (frameinfo_len));
//	fprintf(stderr, "%s DL_receive_frame(): post memcpy\n", nodeinfo.nodename);

	
	inc_link_data(link).infolen += (frameinfo_len);	//counting the packet length
	
	if (f.last_segment > 99) {										//packet complete
		PACKET* pkt = (PACKET*) &inc_link_data(link).curr_info; 	//if transmission was successfull, curr_info will form a well-structured PACKET
		offset = inc_link_data(link).infolen - PACKET_HEADER_SIZE;
		inc_link_data(link).c_curr_part = 0;						//resetting vars for next packet
		inc_link_data(link).infolen = 0;
		if(pkt->len != offset){
			//if(pkt->len < 0 || pkt->len > sizeof(PACKET)){
			//pkt->len = offset; //maybe only length corrupted
			//} else {
				return; //no hope left
			//}
			
		}
		NW_receive_packet(pkt, link);									//pushing packet to the network layer

		
	} else {													//we still don't have the full packet
		inc_link_data(link).c_curr_part++;			
	}
	
	
}
